//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// State Machines and Power Control Register for M8051W/EW
// 
// $Log: m3s010dy.v,v $
// Revision 1.13  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.2  2001/10/31
// First parsable verilog for EW
//
// Revision 1.1.1.1  2001/07/17
// Re-imported E-Warp from Farnham filesystem
//
// Revision 1.11  2000/10/24
// Multiplier rewritten to improve power consumption.
// Code changes for Leonardo (ECN01372).
// Code changes for formal verification tools (ECN01410).
// MOVX @Ri page address controllable from PORT2I if I/O ports ommitted (ECN01387).
//
// Revision 1.10  2000/02/05
// Name change repercussions
//
// Revision 1.9  2000/01/06
// PROGA no longer cleared during idle mode.
// Minor code tidying up.
//
// Revision 1.8  1999/12/08
// Eliminate user instruction during state transition from interrupt service to
// debug state.
// RTL clean up of redundant declarations and sensitvity list entries.
//
// Revision 1.7  1999/12/01
// Fix to Debug State Machine
//
// Revision 1.6  1999/11/30
// More debug changes.
//
// Revision 1.5  1999/11/18
// SFR read enable added, TRAP and DPTR fixes.
//
// Revision 1.4  1999/11/09
// Write PS, TRAP, and EO degugging.
//
// Revision 1.3  1999/11/04
// Further debug changes
//
// Revision 1.2  1999/11/03
// Debug mode revisions.
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
// Revision 1.1  1999/10/22
// Initial revision
//
////////////////////////////////////////////////////////////////////////////////

`include "m8051w_defs.v"
`include "m8051w_cfg.v"

module m3s010dy (STATE, LAST_CYC, INTERNAL_WAIT, INTERNAL_RESET, PCON,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                 NEXT_STATE_IDLE, DebugAck, DebugHold, DebugNOP, DebugPFetch,
		 NCCLKE, NPCLKE, PCLK_EN, PDOWN, REG_RESULT,
                 SFR_WRITE_EN, STATE_CON, RESET, TEST_RESET, EXCEPTION, MWAIT,
                 DebugReq, DebugStep, DebugIUS, TRAP, WRPS, SCLK, CCLK);

  output [2:0]   STATE;                     // clock cycle within instruction
  output         LAST_CYC;                  // last machine cycle of instruction
  output         INTERNAL_WAIT;             // suspend CPU activity
  output         INTERNAL_RESET;            // synchronised reset
  output [7:0]   PCON;                      // PCON SFR
  output         NEXT_STATE_IDLE;           // PC lookahead for IDLE mode
  output         DebugAck;                  // OCI handshake
  output         DebugHold;                 // Mask PC updates
  output         DebugNOP;                  // Insert NOP instruction
  output         DebugPFetch;               // Signal a code byte fetch
  output         NCCLKE;                    // CPU clock qualifier
  output         NPCLKE;                    // peripheral clock qualifier
  output         PCLK_EN;                   // peripheral clock enable
  output         PDOWN;                     // state m/cl clock qualifier

  input  [7:0]   REG_RESULT;                // data input to POWER_CON
  input  [4:4]   SFR_WRITE_EN;              // POWER_CON write strobe
  input  [5:0]   STATE_CON;                 // opcode decode for state machine
  input          EXCEPTION;                 // Interrupt context switch
  input          MWAIT;                     // memory WAIT request
  input          DebugReq;                  // OCI Handshake
  input          DebugStep;                 // OCI machine cycle advance
  input          DebugIUS;                  // Blocking interrupt under service
  input          TRAP;                      // Enter debug mode from TRAP instr
  input          WRPS;                      // Program memory write instruction
  input          TEST_RESET, RESET;         // test & hardware reset
  input          SCLK;                      // state machine clock
  input          CCLK;                      // CPU clock

  reg            PHASE;                     // free-running phase counter
  reg            WAIT_SYNC;                 // registered MWAIT sample
  reg    [2:0]   STATE;
  reg            LAST_CYC;
  reg            INTERNAL_RESET;
  reg            RESET_SAMPLE;
  reg    [4:0]   I_PCON;                    // Internal PCON register
  reg            DebugReqSamp;              // Registered DebugReq
  reg    [1:0]   DebugState;                // Debug state variable
  reg            DebugTail;                 // Synchronise transition to idle

  wire   [7:0]   PCON;                      // External, padded PCON
  wire           NEXT_STATE_IDLE;           // next clock edge is in idle state
  wire           NCCLKE, NPCLKE;            // Clock gating outputs
  wire           PCLK_EN;                   // peripheral clock enable
  wire           PDOWN_RESET;               // Clear powerdoen state
  wire           CodeFetch, DataAccess;      // memory fetch states
  wire           ExternalWait;              // external wait request
  wire           INTERNAL_WAIT;             // suspend CPU activity
  wire           DebugRelease;              // Schedule release from debug state
  wire           DebugWait;                 // Debug wait state request

  // The phase counter and synchronous reset generator.

  always @(posedge SCLK or posedge TEST_RESET)
  begin: p_phase
    // PHASE is only reset by test reset.
    // The compatability reset input is sampled once per machine cycle (end P2).
    if (TEST_RESET) begin
      PHASE <= 1;
      RESET_SAMPLE <= 1'b1;
      INTERNAL_RESET <= 1'b1;
    end
    else begin
      PHASE <= !PHASE;
      if (PHASE) begin
        RESET_SAMPLE <= RESET;
        INTERNAL_RESET <= RESET && RESET_SAMPLE;
      end
    end
  end

  // Instruction State Machine

  always @(posedge CCLK)
  // This state machine runs whenever the processor is not in idle mode or a 
  // memory or debug wait state.
  // The machine cycle count (STATE[2:1]) is reset synchronously via the opcode
  // register.
  begin: p_state
    if (!INTERNAL_WAIT) begin
      STATE[0] <= !PHASE;
      STATE[1] <= STATE_CON[0] && (STATE[1] ^ STATE[0]) && !INTERNAL_RESET &&
                  !TRAP;
      STATE[2] <= STATE_CON[1] && (STATE[2] ^ &STATE[1:0]) && !INTERNAL_RESET;
    end
  end

  // Combinatorial output indicating final machine cycle of the current op.

  always @(STATE or STATE_CON or TRAP)
  begin: p_lcyc
    LAST_CYC <= ~|STATE_CON[1:0] || STATE[1] && !STATE_CON[1] ||
                &STATE[2:1] && STATE_CON[1] || TRAP;
  end

  assign PDOWN_RESET = RESET || TEST_RESET;

  // Power Control Register, PCON

  always @(posedge CCLK)
  begin: p_sync_pcon
    if (INTERNAL_RESET)
      I_PCON[4:2] <= 3'b000;
    else if (SFR_WRITE_EN[4])
        I_PCON[4:2] <= {REG_RESULT[7], REG_RESULT[3:2]};
  end

  // Power Control Register, PCON powerdown mode bits

  always @(posedge SCLK or posedge PDOWN_RESET)
  begin: p_async_pcon
    if(PDOWN_RESET)
      I_PCON[1:0] <= 2'b00;
    else
      if (INTERNAL_RESET)
        I_PCON[1:0] <= 2'b00;
      else begin
        if (SFR_WRITE_EN[4])
          I_PCON[1] <= REG_RESULT[1];
        if (EXCEPTION && !INTERNAL_WAIT)
          I_PCON[0] <= 1'b0;
        else if (SFR_WRITE_EN[4])
          I_PCON[0] <= REG_RESULT[0];
      end
  end

  // Map PCON registers to correct bit positions.
  // Generate idle signal for program counter and opcode register.

  assign PCON = {I_PCON[4], 3'b000, I_PCON[3:0]};
  assign NEXT_STATE_IDLE = (I_PCON[0] || SFR_WRITE_EN[4] && REG_RESULT[0] &&
                           LAST_CYC) && !EXCEPTION && ~|DebugState;

  // Signal code and data byte fetches

  assign CodeFetch = (`CLP2 || `C1P1 && STATE_CON[2] || `C1P2 && STATE_CON[3])
                     && !(DebugState == 2'b01 || DebugState == 2'b11);

  `ifdef muxed_pxram
    assign DataAccess = `C2P1 && STATE_CON[4] || `C1P2 && (STATE_CON[5] || WRPS);
  `else
    assign DataAccess = `C2P1 && STATE_CON[4] || `C1P2 && WRPS || 
                        `CLP2 && STATE_CON[5];
  `endif

  // Wait State Generator
  // Wait states are only entered from memory fetch states

  assign ExternalWait = MWAIT && (CodeFetch && ~|DebugState || DataAccess);

  always @(posedge SCLK or posedge TEST_RESET)
  begin: p_wait_sync
    // Extend wait request to ensure that all wait states are a multiple of two
    // clock periods long.
    if (TEST_RESET)
      WAIT_SYNC <= 0;
    else
      WAIT_SYNC <= ExternalWait && !WAIT_SYNC && !INTERNAL_RESET;
  end

  assign INTERNAL_WAIT = !INTERNAL_RESET &&
                         (ExternalWait || WAIT_SYNC || DebugWait);

  // Debug State Machine
  // Four states:
  // 00 | User Mode
  // 01 | Debug Start
  // 10 | Debug Mode Step
  // 11 | Debug Mode Hold

  always @(posedge SCLK)
  begin: p_debug_state
    if (INTERNAL_RESET) begin
      DebugReqSamp <= 1'b0;
      DebugState <= 2'b00;
      DebugTail <= 1'b0;
    end
    else begin
      if (!PHASE && !ExternalWait && !WAIT_SYNC && !EXCEPTION) begin
        DebugReqSamp <= LAST_CYC? DebugReq: DebugReqSamp;
        DebugState[1] <= DebugState== 2'b00 && TRAP                           ||
                         DebugState== 2'b01 && DebugReq                       ||
  		         DebugState[1] && !DebugRelease;
        DebugState[0] <= DebugState== 2'b00 && DebugReq && !DebugIUS && !TRAP &&
                                                               LAST_CYC       ||
                         DebugState== 2'b01 && DebugReq && !DebugStep         ||
		         DebugState[1] && !DebugRelease && !DebugStep;
      end
      DebugTail <= DebugState[1] && DebugRelease;
    end
  end

  assign DebugRelease = !DebugReq && DebugReqSamp && LAST_CYC;
  assign DebugWait    = PHASE? &DebugState:
                               (DebugState[1] && !DebugRelease && !DebugStep ||
                                DebugState == 2'b01 && !DebugStep);
  assign DebugAck     = DebugState[1];
  assign DebugHold    = |DebugState;
  assign DebugNOP     = DebugState==2'b01;
  assign DebugPFetch  = CodeFetch && !(ExternalWait || WAIT_SYNC);

  // Generate clock qualifiers for optional CPU and peripheral clock gating .

  assign NCCLKE  = I_PCON[1] || I_PCON[0] && ~|DebugState && !DebugTail;
  assign NPCLKE  = I_PCON[1] || !PHASE;
  assign PDOWN   = I_PCON[1];
  assign PCLK_EN = PHASE;
        
endmodule
